from app.log.log import logger

from fastapi.responses import JSONResponse
from tortoise.functions import Max, Sum
from tortoise.transactions import in_transaction

from app.controllers.system.user import user_controller
from app.models import Deposit, Integral, Coupons, Commission, CouponsRole, LevelIntegral, OrdersList, Goods, \
    OrdersGoods
from app.schemas.marketing import CouponsCreate
from app.schemas.users import UserCreate
from app.settings import settings
from app.core.crud import CRUDBase
from app.models.customer import CustomerUser, CustomerLevel
from app.schemas.customer import *
from app.utils.password import get_password_hash, verify_password
from fastapi.exceptions import HTTPException
from tortoise.expressions import Q
import base64
import json
from Crypto.Cipher import AES
from datetime import timedelta, timezone
from app.utils.jwt import create_customer_token


class UsersController(CRUDBase[CustomerUser, CustomerUserCreate, CustomerUserUpdate]):
    def __init__(self):
        super().__init__(model=CustomerUser)

    async def create_user(self, obj_in: CustomerUserCreate) -> CustomerUser:
        #obj_in.password = get_password_hash(password=obj_in.password)
        # 自动生成卡号,按照目前最大卡号+1.annotate(max_price=Max('price')).values('max_price').first()
        ret_max_no = await self.model.annotate(max_no=Max("card_no")).first().values('max_no')
        if ret_max_no["max_no"] is not None:
            max_no = ret_max_no["max_no"] + 1
        else:
            max_no = 1
        # 关联数据
        if obj_in.parent is not None and obj_in.parent != 0:
            parent = await self.model.get(id=obj_in.parent)
            if parent:
                obj_in.parent = parent
            else:
                obj_in.parent = None
        obj_in.card_no = max_no
        obj = await self.create(obj_in)
        return obj

    async def update_user(self, obj_in: CustomerUserUpdate) -> CustomerUser:
        #关联数据
        if obj_in.parent is not None:
            parent = await self.model.get(id=obj_in.parent)
            if parent:
                obj_in.parent = parent
            else:
                obj_in.parent = None
        else:
            obj_in.parent = None
        if obj_in.is_user:
            ret = await user_controller.model.filter(id=obj_in.user_id).first()
            # 查询是否有系统用户账号
            if ret is None:
                user_in = UserCreate(
                    email=obj_in.phone+'@qq.com',
                    username=str(obj_in.phone),
                    password='123456',
                    is_active=True,
                    is_superuser=False,
                )
                # 系统用户生成
                uid = await user_controller.create_user(obj_in=user_in)
                # 设置角色权限为员工
                role_ids = [2]
                await user_controller.update_roles(uid, role_ids)
                obj_in.user_id = uid.id

        obj = await self.update(id=obj_in.id, obj_in=obj_in)
        return obj

    async def update_last_login(self, id: int) -> None:
        user = await self.model.get(id=id)
        user.last_login = datetime.now()
        await user.save()

    async def reset_password(self, user_id: int):
        user_obj = await self.get(id=user_id)
        user_obj.password = get_password_hash(password="123456")
        await user_obj.save()

    async def get_detail(self, user_id: int):
        user_obj = await self.get(id=user_id)
        user_obj.password = None

        return user_obj

    async def level_list(self):
        objs = await CustomerLevel.all().order_by("value").values("id", "name", "value")
        data = dict()
        for obj in objs:
            data[obj['value']] = obj['name']
        return data

    async def list_customer_down(self, search: Q = Q()):
        objs = await self.model.filter(search).all().values("id", "name", "card_no")
        # data = [await obj.to_dict() for obj in objs]
        data = []
        for obj in objs:
            data.append({"value": obj['id'], "label": obj['name'] + "[" + str(obj['card_no']) + "]"})
        return data

    async def authenticate(self, credentials: CredentialsSchema) -> Optional["CustomerUser"]:
        user = await self.model.filter(phone=credentials.name).first()
        if not user:
            raise HTTPException(status_code=400, detail="无效的用户名")
        if not credentials.password == "230307":
            # verified = verify_password(credentials.password, user.password)
            # if not verified:
            raise HTTPException(status_code=400, detail="密码错误!")
        if not user.is_active:
            raise HTTPException(status_code=400, detail="用户已被禁用")
        return user

    async def decrypt_user_phone(self, encrypted_data: str, session_key: str, iv: str) -> str:
        # Base64 decode
        encrypted_data = base64.b64decode(encrypted_data)
        session_key = base64.b64decode(session_key)
        iv = base64.b64decode(iv)
        # AES 解密
        cipher = AES.new(session_key, AES.MODE_CBC, iv)
        decrypted = cipher.decrypt(encrypted_data)
        # 去除填充
        decrypted = self.unpad(decrypted)
        # 转换为字典
        data = json.loads(decrypted.decode('utf-8'))
        return data

    def unpad(self, s: bytes) -> bytes:
        """去除填充"""
        padding_len = s[-1]
        return s[:-padding_len]

    async def mini_login(self, weichatlogin: CustomerWeichatLogin):
        #查询是否存在用户
        user = await CustomerUser.filter(phone=weichatlogin.phone).first()
        if user is None:
            #注册
            try:
                async with in_transaction() as transaction:
                    # 注册
                    data = {
                        "name": "微信用户",
                        "phone": weichatlogin.phone,
                        "parent": weichatlogin.user_id,
                        "open_id": weichatlogin.open_id,
                        "space_id": weichatlogin.space_id,
                    }

                    obj_in = CustomerUserCreate(**data)
                    ret = await self.create_user(obj_in)
                    if ret:
                        logger.info(f"获得邀请奖励优惠券")
                        # Import here to avoid circular dependency
                        from app.controllers.marketing.coupons import coupons_controller
                        coupons_data = CouponsCreate(
                            user_id=ret.id,
                            coupons_id=8,
                            coupons_price=0,
                            expire_at="",
                            is_used=0,
                            come_type=4,
                            add_order_id=0,
                            order_goods_id=0,
                            remark=f"新用户注册邀请奖励",
                            space_id=weichatlogin.space_id,
                        )
                        await coupons_controller.do_create(obj_in=coupons_data)
            except Exception as e:
                return JSONResponse(content={"code": 400, "message": f"创建过程中发生错误{e}"}, status_code=400)
        else:
            await CustomerUser.filter(phone=weichatlogin.phone).update(open_id=weichatlogin.open_id)
        data = {
            "name": weichatlogin.phone,
            "password": "230307",
        }
        credentials = CredentialsSchema(**data)
        ret = await self.get_token(credentials)
        return ret

    async def get_token(self, credentials: CredentialsSchema):
        user: CustomerUser = await self.authenticate(credentials)
        await self.update_last_login(user.id)
        access_token_expires = timedelta(minutes=settings.JWT_ACCESS_TOKEN_EXPIRE_MINUTES)
        expire = datetime.now(timezone.utc) + access_token_expires
        data = CustomerJWTOut(
            access_token=create_customer_token(
                data=CustomerJWTPayload(
                    user_id=user.id,
                    username=user.name,
                    exp=expire,
                )
            ),
            username=user.name,
        )
        return data.model_dump()

    ##更新资产
    async def update_money(self, type: int, user_id: int):
        money = 0.00
        if type == 1:
            ##储值金
            result = await Deposit.filter(user_id=user_id, direction=1).annotate(
                add_price=Sum('price')
            ).first()
            add_price = result.add_price if result.add_price else 0.00
            result = await Deposit.filter(user_id=user_id, direction=2).annotate(
                del_price=Sum('price')
            ).first()
            del_price = result.del_price if result.del_price else 0.00
            money = round(float(add_price) - float(del_price), 2)
            # 实际金额
            # 查出储值金所有订单id
            deposits = await Deposit.filter(user_id=user_id, direction=1).all()
            order_ids = [deposit.order_id for deposit in deposits]
            print(order_ids,2131)
            # 查出所有储值商品
            goods = await Goods.filter(get_deposit__gt=0,get_deposit_max__gt=0).all()
            good_ids = [good.id for good in goods]
            print(good_ids, 2131)
            prices = await OrdersGoods.filter(user_id=user_id,goods_id__in=good_ids,order_id__in=order_ids).values('price')
            print(prices, 2131)
            zs_price = 0.0
            for price in prices:
                zs_price += float(price['price'])

            total_price = float(add_price) - zs_price  # 全部转为float
            await CustomerUser.filter(id=user_id).update(money_deposit=money,money_zs_deposit=total_price)
            print(1231, 2131)
        elif type == 2:
            ##积分
            result = await Integral.filter(user_id=user_id, direction=1).annotate(
                add_price=Sum('price')
            ).first()
            add_price = result.add_price if result.add_price else 0.00
            result = await Integral.filter(user_id=user_id, direction=2).annotate(
                del_price=Sum('price')
            ).first()
            del_price = result.del_price if result.del_price else 0.00
            money = round(float(add_price) - float(del_price), 2)
            await CustomerUser.filter(id=user_id).update(money_integral=money)

        elif type == 3:
            ##优惠券
            result = await Coupons.filter(user_id=user_id, is_used=0).annotate(
                add_price=Sum('coupons_price')
            ).first()
            money = result.add_price if result.add_price else 0.00
            await CustomerUser.filter(id=user_id).update(money_coupons=money)

        elif type == 4:
            ##佣金
            result = await Commission.filter(user_id=user_id).annotate(
                add_price=Sum('price')
            ).first()
            money = result.add_price if result.add_price else 0.00
            await CustomerUser.filter(id=user_id).update(money_commission=money)

        elif type == 5:
            ##等级积分
            result = await LevelIntegral.filter(user_id=user_id, direction=1).annotate(
                add_price=Sum('price')
            ).first()
            add_price = result.add_price if result.add_price else 0.00
            result = await LevelIntegral.filter(user_id=user_id, direction=2).annotate(
                del_price=Sum('price')
            ).first()
            del_price = result.del_price if result.del_price else 0.00
            money = round(float(add_price) - float(del_price), 2)
            await CustomerUser.filter(id=user_id).update(level_integral=money)
            ##这里还要查询客户是否升级
            # level_data = await CustomerLevel.filter(level_integral__lte=money).order_by("-value").first().values("value")
            # if level_data:
            #     await CustomerUser.filter(id=user_id).update(role_id=level_data['value'])
        return money

    async def get_visit(self,page: int, page_size: int, user_id: int):
        query = self.model.filter(parent_id=user_id)
        total = await query.count()
        objs = await query.offset((page - 1) * page_size).limit(page_size).order_by("-id")
        data = [await obj.to_dict() for obj in objs]
        return total,data

users_controller = UsersController()
